<?php
/*
 * @Author: 杨红兵 
 * @Date: 2022-07-13 15:21:18 
 * @Last Modified by: 杨红兵
 * @Last Modified time: 2022-07-13 17:27:40
 */

namespace app\libraries\utils\log;

use app\libraries\utils\Trace;
use Error;
use Swoole\Coroutine;
use think\log\driver\File as DriverFile;

class File extends DriverFile
{
    /**
     * 日志写入接口
     * @access public
     * @param array $log 日志信息
     * @return bool
     */
    public function save(array $log): bool
    {
        $destination = $this->getMasterLogFile();
        $path = dirname($destination);
        if (!is_dir($path)) {
            @mkdir($path, 0777, true);
            @chmod($path, 0777);
        }
        $info = [];
        // 日志信息封装
        $url = Trace::getInstance()->isCommand() ? Trace::getInstance()->getCommand() : Trace::getInstance()->getUrl();
        $url = empty(trim($url)) ? Trace::getInstance()->getUrl() : $url;
        $timeSpan = time();
        $microTime = getmicrotime();
        $time = \DateTime::createFromFormat(
            '0.u00 U',
            microtime()
        )
            ->setTimezone(new \DateTimeZone(date_default_timezone_get()))->format(
                $this->config['time_format']
            );
        foreach ($log as $type => $val) {
            $message = $this->getLogInfo($val, $timeSpan, $time, $microTime, $type, $path, $url);
            if ($message === false) {
                continue;
            }
            $info[$type] = $message;
        }
        if ($info) {
            return $this->write($info, $destination);
        }

        return true;
    }

    /**
     * 处理日志内容
     *
     * @Author YangHB
     * @DateTime 2022-07-12 09:46:30
     *
     * @param array $val
     * @param int $timeSpan
     * @param string $time
     * @param string|int $type
     * @param string $path
     * @param string $url
     * @return array|bool
     */
    protected function getLogInfo(array $val, int $timeSpan, string $time, string $microTime, $type, string $path, string $url)
    {
        $message = [];
        foreach ($val as $msg) {
            if ($this->config['json']) {
                if (!is_array($msg)) {
                    $msg = [
                        'title' => 'old_log_handle',
                        'msg' => $msg,
                    ];
                }
                unset($msg['timestamp']);
                unset($msg['time']);
                unset($msg['microtime']);
                unset($msg['level']);
                $msg = array_map(function ($item) {
                    if (!is_string($item)) {
                        $item = json_encode($item, JSON_UNESCAPED_UNICODE);
                    }
                    return $item;
                }, $msg);
                $msg = array_merge($msg, [
                    'project_name' => config('app.project_name'),
                    'env' => config('app.env'),
                    'run_env' => '' . getenv('POD_NODE_ENV'),
                    'run_pod' => '' . getenv('POD_NAMESPACE') . getenv('POD_NUMBER'),
                    'pod_name' => '' . getenv('POD_APPNAME'),
                    'server_name' => Trace::getInstance()->getHost(),
                    'url' => $url,
                    'path' => Trace::getInstance()->getPath(),
                    'grant_type' => Trace::getInstance()->getGrantType(),
                    'come_from' => Trace::getInstance()->getComeFrom(),
                    'all_trace_id' => Trace::getInstance()->getTraceId(),
                    'pre_trace_id' => Trace::getInstance()->getPreTraceId(),
                    'now_trace_id' => Trace::getInstance()->getNowTraceId(),
                    //'file_line' => Trace::getContainer()->getFileLine(),
                ]);
            } elseif (!is_string($msg)) {
                $msg = var_export($msg, true);
            }
            $message[] = $this->config['json'] ?
                json_encode(array_merge(
                    [
                        'timestamp' => $timeSpan,
                        'time' => $time,
                        'microtime' => $microTime,
                        'level' => $type
                    ],
                    $msg
                ), $this->config['json_options']) :
                sprintf($this->config['format'], $time, $type, $msg);
        }
        if (true === $this->config['apart_level'] || in_array($type, $this->config['apart_level'])) {
            // 独立记录的日志级别
            $filename = $this->getApartLevelFile($path, $type);
            $this->write($message, $filename);
            return false;
        }
        return $message;
    }

    /**
     * 日志写入
     * @access protected
     * @param array  $message     日志信息
     * @param string $destination 日志文件
     * @return bool
     */
    protected function write(array $message, string $destination): bool
    {
        if (!is_file($destination)) {
            $first = true;
        }
        $ret = parent::write($message, $destination);
        try {
            if (isset($first) && is_file($destination)) {
                @chmod($destination, 0777);
                unset($first);
            }
        } catch (Error $e) {
            unset($e);
        }
        return $ret;
    }
}
